
package domain;

import domain.exceptions.*;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Iterator;
import java.util.Vector;

/**
 *
 * @author shaigi
 */
public class Board {

    private String          _fileName;
    private Square[][]      _board;
    private int             _numberOfRows;
    private int             _numberOfColumns;
    private Vector<Flag>    _flags;
    
    public Board(String fileName){
        this._fileName  = fileName;
        this._flags     = new Vector<Flag>();
        initializeBoard();
        parse();
    }
    
    public Square getSquare(int row, int column){
        return _board[row][column];
    }
    
    public void placeAgent(Agent agent, Square square) throws CannotPlaceAgentHereException{
        try{
            _board[square.getColumn()][square.getRow()].placeAgent(agent);
            agent.setSquare(square);
        } catch (CannotPlaceAgentHereException e){
            throw e;
        }
    }
    
    public void removeAgent(int x, int y) throws Exception{
        try{
            _board[x][y].removeAgent();
        } catch (Exception e){
            throw new Exception(e.getMessage());
        }
    }

    Vector<Flag> getFlags() {
        return this._flags;
    }

    public void removeFlag(Square square) throws TryingToRemoveNonExistingFlagException {
        boolean found = false;
        for (Iterator<Flag> it = _flags.iterator(); it.hasNext();) {
            Flag flag = it.next();
            if (flag.getSquare().equals(square)){
                _flags.remove(flag);
                found = true;
            }
        }
        if ( !found )
            throw new TryingToRemoveNonExistingFlagException();
    }

    private void initializeBoard() {
        int rowsTmp = 0;
        BufferedReader in = null;
        String str = "";
        try {
            in = new BufferedReader(new FileReader(_fileName));
        } catch (FileNotFoundException ex) {
            
        }
        try {
            while ((str = in.readLine()) != null) {
                rowsTmp++;
            }
        } catch (IOException ex) {
            System.out.println(ex.getMessage());
        }
        this._numberOfRows    = rowsTmp;
        try {
            in = new BufferedReader(new FileReader(_fileName));
            str = in.readLine();
        } catch (IOException ex) {
            System.out.println(ex.getMessage());
        }
        this._numberOfColumns = str.length();
        this._board = new Square[_numberOfRows][_numberOfColumns];
    }

    private void parse() {
        int row    = 0;
        try {
            BufferedReader in = new BufferedReader(new FileReader(_fileName));
            String str;
            while ((str = in.readLine()) != null) {
                process(str, row);
                row++;
            }
            in.close();
        } catch (IOException e) {
            System.out.println(e.getMessage());
        }        
    }

    private void process(String str, int row) {
        
        for (int column=0; column<str.length(); column++){
            char c = str.charAt(column);
            switch (c){
                case ' ':       // empty square
                    _board[row][column] = new SquareFree(row, column);
                    break;
                case '#':       // wall
                    _board[row][column] = new SquareWall(row, column);
                    break;
                case 'F':       // flag
                    Square newSquare = new SquareFree(row, column);
                    _board[row][column] = newSquare;
                    try {
                        //_board[row][column].setFlag(Game.FLAG_COST);
                        Flag newFlag = new Flag(newSquare, Game.FLAG_COST);
                        _board[row][column].setFlag(newFlag);
                        _flags.addElement(newFlag);
                    } catch (CannotFlagWallSquareException ex) {
                        System.out.println("This line will never be reached");
                    }
                    //_board[row][column] = new SquareFlag(row, column, Game.FLAG_COST);
                    break;
                case '.':       // icy patch
                    _board[row][column] = new SquareIce(row, column);
                    break;
            }
        }
    }

    public String getFileName() {
        return _fileName;
    }

    public int getNumberOfRows() {
        return _numberOfRows;
    }

    public int getNumberOfColumns() {
        return _numberOfColumns;
    }
    
    public boolean inSight(Square squareShooter, Square squareVictim) throws MultipleAgentsHaveTheSameLocation {
        boolean ans=true;
        int x1=squareShooter.getRow();
        int y1=squareShooter.getColumn();
        int x2=squareVictim.getRow();
        int y2=squareVictim.getColumn();
        //checking if the row or col are equal, if not returning false.
        if(x1!=x2&&y1!=y2){
            return false;
        }
        // checks if there's an obstacle in shooter's row:
        else if(x1==x2){
            for( int i=Math.min(y1, y2)+1;i<Math.max(y1,y2) && ans; i++){
                if(_board[x1][i] instanceof SquareWall  ||  _board[x1][i].isAgentHere()){
                    ans = false;
                }
            }
        }
        // checks if there's an obstacle in shooter's column:
        else if(y1==y2){
            for( int i=Math.min(x1, x2)+1;i<Math.max(x1,x2) && ans;i++){
                if(_board[i][y1] instanceof SquareWall  ||  _board[i][y1].isAgentHere()){
                    ans = false;
                }
            }
        }
        return ans;
    }//end of inSight
    
    @Override
    public Board clone(){
        Board ans = null;
        String          fileNameNew = this._fileName;
        int             numberOfRowsNew = this._numberOfRows;
        int             numberOfColumnsNew = this._numberOfColumns;
        Vector<Flag>    flagsNew = (Vector<Flag>) this._flags.clone();
        Square[][]      boardNew = new Square[numberOfRowsNew][numberOfColumnsNew];
        for (int i = 0; i < numberOfRowsNew; i++) {
            for (int j = 0; j < numberOfColumnsNew; j++) {
                Square sq = boardNew[i][j];
                if ( sq instanceof SquareWall ){
//                    boardNew[i][j] = ((SquareWall)_board[i][j])
                            SquareWall sqw=new SquareWall(j, j);
                }
                
            }
            Square[] squares = boardNew[i];
            
        }
        
        return ans;
    }
}
